﻿using System;
using System.IO;
using System.Text;

namespace XmWpfBase.Common
{
    public static class ErrorLogger
    {
        private static readonly string LogDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "logs");
        private static readonly string LogFilePath = Path.Combine(LogDirectory, "error.log");
        private static readonly object LogLock = new object();

        /// <summary>
        /// 记录错误信息到日志文件
        /// </summary>
        /// <param name="exception">异常对象</param>
        /// <param name="context">错误上下文信息</param>
        public static void LogError(Exception exception, string context = "")
        {
            try
            {
                // 确保日志目录存在
                EnsureLogDirectoryExists();

                // 构建日志内容
                string logContent = BuildLogContent(exception, context);

                // 写入日志文件
                WriteToLogFile(logContent);
            }
            catch (Exception ex)
            {
                // 如果日志记录失败，尝试写入系统事件日志
                try
                {
                    System.Diagnostics.EventLog.WriteEntry("XmWpfBase", 
                        $"日志记录失败: {ex.Message}\n原始错误: {exception?.Message}", 
                        System.Diagnostics.EventLogEntryType.Error);
                }
                catch
                {
                    // 忽略系统事件日志写入失败
                }
            }
        }

        /// <summary>
        /// 记录一般信息到日志文件
        /// </summary>
        /// <param name="message">信息内容</param>
        /// <param name="level">日志级别</param>
        public static void LogInfo(string message, string level = "INFO")
        {
            try
            {
                EnsureLogDirectoryExists();

                string logContent = $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] [{level}] {message}\n" +
                                  "----------------------------------------\n\n";

                WriteToLogFile(logContent);
            }
            catch
            {
                // 忽略信息日志记录失败
            }
        }

        private static void EnsureLogDirectoryExists()
        {
            if (!Directory.Exists(LogDirectory))
            {
                Directory.CreateDirectory(LogDirectory);
            }
        }

        private static string BuildLogContent(Exception exception, string context)
        {
            var sb = new StringBuilder();
            
            sb.AppendLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] [ERROR] {context}");
            sb.AppendLine($"异常类型: {exception.GetType().FullName}");
            sb.AppendLine($"错误消息: {exception.Message}");
            
            if (!string.IsNullOrEmpty(exception.Source))
            {
                sb.AppendLine($"错误源: {exception.Source}");
            }

            if (exception.TargetSite != null)
            {
                sb.AppendLine($"目标方法: {exception.TargetSite}");
            }

            sb.AppendLine("堆栈跟踪:");
            sb.AppendLine(exception.StackTrace ?? "无堆栈跟踪信息");

            // 记录内部异常
            if (exception.InnerException != null)
            {
                sb.AppendLine("\n内部异常:");
                sb.AppendLine(BuildInnerExceptionContent(exception.InnerException, 1));
            }

            // 记录额外的系统信息
            sb.AppendLine($"\n系统信息:");
            sb.AppendLine($"操作系统: {Environment.OSVersion}");
            sb.AppendLine($"CLR版本: {Environment.Version}");
            sb.AppendLine($"工作目录: {Environment.CurrentDirectory}");
            sb.AppendLine($"机器名: {Environment.MachineName}");
            sb.AppendLine($"用户名: {Environment.UserName}");

            sb.AppendLine("========================================\n");

            return sb.ToString();
        }

        private static string BuildInnerExceptionContent(Exception innerException, int level)
        {
            var sb = new StringBuilder();
            string indent = new string(' ', level * 2);

            sb.AppendLine($"{indent}异常类型: {innerException.GetType().FullName}");
            sb.AppendLine($"{indent}错误消息: {innerException.Message}");
            
            if (!string.IsNullOrEmpty(innerException.StackTrace))
            {
                sb.AppendLine($"{indent}堆栈跟踪:");
                var stackLines = innerException.StackTrace.Split('\n');
                foreach (var line in stackLines)
                {
                    sb.AppendLine($"{indent}{line}");
                }
            }

            if (innerException.InnerException != null)
            {
                sb.AppendLine($"{indent}内部异常:");
                sb.AppendLine(BuildInnerExceptionContent(innerException.InnerException, level + 1));
            }

            return sb.ToString();
        }

        private static void WriteToLogFile(string content)
        {
            lock (LogLock)
            {
                // 检查日志文件大小，如果超过10MB则备份
                if (File.Exists(LogFilePath))
                {
                    var fileInfo = new FileInfo(LogFilePath);
                    if (fileInfo.Length > 10 * 1024 * 1024) // 10MB
                    {
                        BackupLogFile();
                    }
                }

                // 追加写入日志文件
                File.AppendAllText(LogFilePath, content, Encoding.UTF8);
            }
        }

        private static void BackupLogFile()
        {
            try
            {
                string backupFileName = $"error_{DateTime.Now:yyyyMMdd_HHmmss}.log";
                string backupFilePath = Path.Combine(LogDirectory, backupFileName);
                
                File.Move(LogFilePath, backupFilePath);
                
                // 清理旧的备份文件，只保留最近10个
                CleanupOldBackups();
            }
            catch
            {
                // 如果备份失败，清空当前日志文件
                File.WriteAllText(LogFilePath, string.Empty);
            }
        }

        private static void CleanupOldBackups()
        {
            try
            {
                var backupFiles = Directory.GetFiles(LogDirectory, "error_*.log");
                if (backupFiles.Length > 10)
                {
                    Array.Sort(backupFiles);
                    for (int i = 0; i < backupFiles.Length - 10; i++)
                    {
                        File.Delete(backupFiles[i]);
                    }
                }
            }
            catch
            {
                // 忽略清理失败
            }
        }

        /// <summary>
        /// 获取日志文件路径
        /// </summary>
        /// <returns>日志文件完整路径</returns>
        public static string GetLogFilePath()
        {
            return LogFilePath;
        }

        /// <summary>
        /// 获取日志目录路径
        /// </summary>
        /// <returns>日志目录完整路径</returns>
        public static string GetLogDirectory()
        {
            return LogDirectory;
        }
    }
}
